package com.nekonomics
package persistence.repository

import domain.entity.Merchant
import utils.SqlUtil
import utils.magic.SqlMagic

import doobie.*
import doobie.implicits.*
import doobie.postgres.implicits.*
import zio.*
import zio.interop.catz.*


trait MerchantRepo {
  def findById(id: Long): ConnectionIO[Option[Merchant]]

  def findBySpuId(spuId: Long): ConnectionIO[Option[Merchant]]

  def getBySpuId(spuId: Long): ConnectionIO[Merchant]

  def findByUserId(userId: Long): ConnectionIO[Option[Merchant]]
}

object MerchantRepo {
  val live: ULayer[MerchantRepo] = ZLayer.succeed(new MerchantRepoLive)
}

class MerchantRepoLive extends MerchantRepo {
  override def findById(id: Long): ConnectionIO[Option[Merchant]] =
    SqlUtil.selectFromWhereOpt[Merchant](Some(fr"id = $id"))
      .query[Merchant]
      .option


  override def findBySpuId(spuId: Long): ConnectionIO[Option[Merchant]] = {
    val fields = SqlMagic.fieldSnakeNames[Merchant]
    (fr"select "
      ++ Fragment.const(SqlUtil.fieldsWithAlias(fields, Some("m")))
      ++ fr"from public.merchant as m"
      ++ fr"join public.spu as s on s.id = $spuId and m.id = s.merchant_id")
      .query[Merchant]
      .option
  }

  override def getBySpuId(spuId: Long): doobie.ConnectionIO[Merchant] = {
    findBySpuId(spuId)
      .map(_.get)
  }


  override def findByUserId(userId: Long): doobie.ConnectionIO[Option[Merchant]] = {
    val fields = SqlUtil.fieldsWithAlias(SqlMagic.fieldSnakeNames[Merchant], Some("merchant"))
    SqlUtil
      .selectFromWhereOpt[Merchant](Some(fr"merchant.user_id = $userId"))
      .query[Merchant]
      .option
  }
}
